package com.hot12345.springmvc;

import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;

import com.hot12345.dao.ItemDaoImpl;
import com.hot12345.entity.Item;
import com.hot12345.entity.User;
import com.hot12345.service.CookieService;
import com.hot12345.service.LoginService;

/**
 * 拦截spring mvc的controller，获取request进行数据初始化和权权限认证等。(前后台通用)
 * @author wuzongbao
 *
 */
@Aspect
@Component
public class SpringControllerAop implements Ordered {
	private final static Log log = LogFactory.getLog(SpringControllerAop.class);
	
//	 * @Pointcut 创建拦截点
//	 * @Before 在拦载的方法前调用，除非抛出异常，否则不能停止方法的调用。
//	 * @Around 在拦载的方法前后调用 与ProceedingJoinPoint配置使用，可以设置是否执行拦截方法。
//	 * @After 在拦载的方法后调用，除非抛出异常，否则不能停止方法的调用。
//	例子：
//	1）execution(* *(..)) 第一个*表示所有类型(public,private...)的类,每二个*表示所有的方法，(..)所有的参数
//	表示匹配所有方法
//	2）execution(public * com. savage.service.UserService.*(..))
//	表示匹配com.savage.server.UserService中所有的公有方法
//	3）execution(* com.savage.server..*.*(..))
//	表示匹配com.savage.server包及其子包下的所有方法
	
	//execution (public * com.tianyaclub.springmvc.companyasystem.*.*(..))
	
	@Pointcut("execution (public * com.hot12345.springmvc..*.*(..))")
	public void global(){
	}
	
	@Pointcut("execution (public * com.hot12345.springmvc.admin..*.*(..))")
	public void admin(){
	}
	
	
	//springmvc下全局拦截处理
	@Around("global()")
	public Object globalJoinPoint(ProceedingJoinPoint  point) throws Throwable{
		//获取方法的参数request,response,ModelMap 必须要有这三个参数
		Object[] args = point.getArgs();
		HttpServletRequest request = null;
		HttpServletResponse response = null;
		ModelMap modelMap = null;
		if(args!=null && args.length>0){
			for(Object obj : args){
				if(obj instanceof HttpServletRequest){
					request = (HttpServletRequest)obj;
				} else if(obj instanceof HttpServletResponse){
					response = (HttpServletResponse)obj;
				} else if(obj instanceof ModelMap){
					modelMap = (ModelMap)obj;
				}
			}
		}
		
		if(request==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
		}
		if(response==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少response参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "缺少response参数");
		}
		if(modelMap==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "的方法缺少modelMap参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "的方法缺少modelMap参数");
		}

		
//		/**
//		 * 过滤请求参数中的特殊字符
//		 */
//		boolean filterParams = true;
//		try {
//			filterParams = AuthInterceptor.filterPara(request);
//		} catch (Exception e1) {
//			log.error("过滤参数中特殊字符出现异常",e1);
//		}
//		/**
//		 * 如果返回者为true表明包含特殊字符
//		 */
//		if(filterParams)
//		{
//			request.setAttribute("error", "无效访问，请求中包含非法参数！");
//			request.getRequestDispatcher("/error/error.jsp").forward(request, response);
//			return null;
//		}
	
		
		//对Controller的方法抛出的异常进行捕获，把异常信息记录到日志文件。
		Object object = null;
		try{
			object = point.proceed();
		}catch(Throwable e){
			log.error("Throwable",e);
			throw new Throwable(e);
		}
		
		return object;
	}
	
	@Around("admin()")
	public Object adminJoinPoint(ProceedingJoinPoint point) throws Throwable{
		//获取方法的参数request,response,ModelMap 必须要有这三个参数
		Object[] args = point.getArgs();
		HttpServletRequest request = null;
		HttpServletResponse response = null;
		ModelMap modelMap = null;
		if(args!=null && args.length>0){
			for(Object obj : args){
				if(obj instanceof HttpServletRequest){
					request = (HttpServletRequest)obj;
				} else if(obj instanceof HttpServletResponse){
					response = (HttpServletResponse)obj;
				} else if(obj instanceof ModelMap){
					modelMap = (ModelMap)obj;
				}
			}
		}
		
		if(request==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
		}
		if(response==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少response参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "缺少response参数");
		}
		if(modelMap==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "的方法缺少modelMap参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "的方法缺少modelMap参数");
		}	
		
//		User user = (User)request.getSession().getAttribute("user");
//		if((user==null || user.getId()==null) && !LoginService.isOnline(request)){
		if(!LoginService.isOnline(request)){//暂时只作cookie判断
			String uri = request.getRequestURI();
			String queryString = request.getQueryString();
			if(queryString!=null && !"null".equals(queryString.trim())){
				uri += "?"+queryString;
			}
			if(uri==null || "".equals(uri.trim())){
				uri = "/admin/index";
			}
			uri = URLEncoder.encode(uri, "UTF-8");
			response.sendRedirect("/admin/login/index?forwardURL=http://www.hot12345.com"+uri);
			return null;
		}

		/**
		HttpSession session = request.getSession();
		User sessionUser = (User)session.getAttribute("user");
		if(sessionUser==null){
//			request.getRequestDispatcher("/login.jsp").forward(request, response);
			String uri = request.getRequestURI();
			String queryString = request.getQueryString();
			if(queryString!=null && !"null".equals(queryString.trim())){
				uri += "?"+queryString;
			}
			if(uri==null || "".equals(uri.trim())){
				uri = "/admin/index";
			}
//			if(uri!=null && !"".equals(uri.trim())){
//				uri = "&"+uri;
//			}
			uri = URLEncoder.encode(uri, "UTF-8");
			response.sendRedirect("/admin/login/index?forwardURL=http://www.hot12345.com"+uri);
			return null;
		}
		*/
		
		User loginUser = new User();
		loginUser.setId(CookieService.getCookieByName(request, "userID")==null?null:Integer.valueOf(CookieService.getCookieByName(request, "userID").getValue()));
		loginUser.setName(CookieService.getCookieByName(request, "userName")==null?null:CookieService.getCookieByName(request, "userName").getValue());
		modelMap.put("loginUser", loginUser);
		modelMap.put("userID", CookieService.getCookieByName(request, "userID")==null?null:CookieService.getCookieByName(request, "userID").getValue());
		modelMap.put("userName", CookieService.getCookieByName(request, "userName")==null?null:CookieService.getCookieByName(request, "userName").getValue());
		
		//导航需要显示所有栏目
		ItemDaoImpl itemDao = ItemDaoImpl.getInstance();
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("state", 1);
		List<Item> itemList = itemDao.findByParams(map);
		modelMap.put("itemList", itemList);
		
		//对Controller的方法抛出的异常进行捕获，把异常信息记录到日志文件。
		Object object = null;
		try{
			object = point.proceed();
		}catch(Throwable e){
			log.error("Throwable",e);
			throw new Throwable(e);
		}
		
		return object;
	}
	
	public int getOrder() {
		// TODO Auto-generated method stub
		return 0;
	}
	
	//因为每个入拦截都需要进行这些判断，故抽出来
	public void paramsCheck(JoinPoint point,HttpServletRequest request,HttpServletResponse response,ModelMap modelMap) throws Exception{
		
		if(request==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
		}
		if(response==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "方法缺少request参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "缺少request参数");
		}
		if(modelMap==null){
			log.error(point.getTarget()+"的"+ point.getSignature().getName() + "的方法缺少request参数");
			throw new Exception(point.getTarget()+"的"+ point.getSignature().getName() + "的方法缺少request参数");
		}
	}
}
